﻿#include "VulkanMeshInstances.h"
#include "Render/Scene/VulkanScene.h"
#include "Render/Widget/VulkanViewportWidget.h"
#include "Render/Scene/VulkanPointLights.h" 
#include "Render/Scene/VulkanSpotLights.h"
#include "Render/Scene/VulkanDirectionalLights.h"
#include "Render/Material/VulkanMaterial.h"

#include "Shaders/CppMacros.h"

#include "Render/PreRender/PreRenderMesh.h"
#include "Render/PreRender/PreRenderMaterial.h"

#include "Render/Mesh/VulkanMesh.h"
#include "Render/Material/VulkanMaterial.h"

void CVulkanMeshInstances::PreProcess(
    const TVector<SPreRenderMeshInstance>& InMeshInstance
    ,CVulkanViewportWidget * InViewport
    ,CVulkanScene* InScene
    )
{
    MeshInstances.Clear();
    ViewportMeshInstanceBatches.Clear();
    PointLightShadowMapMeshMap.Clear();
    auto PointLightPainter = InScene->GetPointLightPainter();
    int64_t PointLightNum = PointLightPainter->GetPointLightNum();
    PointLightShadowMapMeshMap.Resize(PointLightNum);

    SpotLightShadowMapMeshMap.Clear();
    auto SpotLightPainter = InScene->GetSpotLightPainter();
    int64_t SpotLightNum = SpotLightPainter->GetSpotLightNum();
    SpotLightShadowMapMeshMap.Resize(SpotLightNum);

    DirectionalLightShadowMapMeshMap.Clear();
    auto DirectionalLightPainter = InScene->GetDirectionalLightPainter();
    int64_t DirectionalLightNum = DirectionalLightPainter->GetDirectionalLightNum();
    DirectionalLightShadowMapMeshMap.Resize(DirectionalLightNum);

    //剔除不参与渲染的网格实例
    TVector<int64_t> ViewportMeshMap;
    int64_t MeshInstanceIndex=0;
    for (const auto& MeshInstance : InMeshInstance)
    {
        //检查是否在视椎体内
        bool bIsInViewport = InViewport->FastIsSphereIntersectFrustum(
            MeshInstance.Position
            , MeshInstance.BoundingSphereRadius);


        //检查是否能被光照，即便不在视椎体内也可能参与阴影贴图生成
        if(!MeshInstance.CastShadow && !bIsInViewport)
        {
            //既不在视椎体内也不参与阴影贴图生成
            //不参与渲染
            continue;
        }

        bool bForShadowMap = false;
        if(MeshInstance.CastShadow)
        {

            //检查是否在光源范围内
            // auto PointLightPainter = InScene->GetPointLightPainter();
            // int64_t PointLightNum = PointLightPainter->GetPointLightNum();
            // PointLightShadowMapMeshMap.Resize(PointLightNum);
            for(int64_t LightIndex=0;LightIndex<PointLightNum;++LightIndex)
            {

                if(PointLightPainter->IsInLightRange(
                    LightIndex
                    ,MeshInstance.Position
                    ,MeshInstance.BoundingSphereRadius
                    ))
                {
                    bForShadowMap = true;
                    PointLightShadowMapMeshMap[LightIndex].Add(MeshInstanceIndex);
                }
            }

            //检查是否在聚光灯范围内
            // auto SpotLightPainter = InScene->GetSpotLightPainter();
            // int64_t SpotLightNum = SpotLightPainter->GetSpotLightNum();
            // SpotLightShadowMapMeshMap.Resize(SpotLightNum);
            for(int64_t LightIndex=0;LightIndex<SpotLightNum;++LightIndex)
            {
                if(SpotLightPainter->IsInLightRange(
                    LightIndex
                    ,MeshInstance.Position
                    ,MeshInstance.BoundingSphereRadius
                    ))
                {
                    bForShadowMap = true;
                    SpotLightShadowMapMeshMap[LightIndex].Add(MeshInstanceIndex);
                }
            }

            //检查是否在方向光范围内
            // auto DirectionalLightPainter = InScene->GetDirectionalLightPainter();
            // int64_t DirectionalLightNum = DirectionalLightPainter->GetDirectionalLightNum();
            // DirectionalLightShadowMapMeshMap.Resize(DirectionalLightNum);
            for(int64_t LightIndex=0;LightIndex<DirectionalLightNum;++LightIndex)
            {
                if(DirectionalLightPainter->IsInLightRange(
                    LightIndex
                    ,MeshInstance.Position
                    ,MeshInstance.BoundingSphereRadius
                    ))
                {
                    bForShadowMap = true;
                    
                    for(int32_t MeshSection=0; MeshSection<MeshInstance.MeshSections.Num();MeshSection++)
                    {
                        auto PreRenderMesh=MeshInstance.MeshSections[MeshSection];
                        auto Mesh=CVulkanContext::Get()->ToVulkanMesh(PreRenderMesh->WriteInData);
                        if(!DirectionalLightShadowMapMeshMap[LightIndex].Contains(Mesh))
                        {
                            DirectionalLightShadowMapMeshMap[LightIndex].Add(Mesh,SVulkanShadowmapMeshBatch(Mesh));
                        }

                        DirectionalLightShadowMapMeshMap[LightIndex][Mesh].ModelMatrices.Add(MeshInstance.GetModelMatrix());

                    }

                    
                    
                }
            }
        }

        if(!bForShadowMap && !bIsInViewport)
        {
            //既不在视椎体内也不用于阴影贴图生成
            //不参与渲染
            continue;
        }

        if(bIsInViewport)
        {
            ViewportMeshMap.Add(MeshInstanceIndex);
        }

        MeshInstances.Add(CVulkanMeshInstance());
        MeshInstances.Last().SetData(MeshInstance);
        ++MeshInstanceIndex;


    }

    //合批，有相同网格和材质即可合为一批
    for(auto& MeshInstanceIndex: ViewportMeshMap)
    {
        auto& MeshInstance=MeshInstances[MeshInstanceIndex];
        for(int32_t SectionIndex=0;SectionIndex<MeshInstance.MeshSections.Num();++SectionIndex)
        {
            auto Mesh=MeshInstance.MeshSections[SectionIndex];
            auto Material = MeshInstance.Materials[SectionIndex];

            SBatchKey BatchKey;
            BatchKey.Mesh = Mesh;
            BatchKey.Material = Material;

            if(!ViewportMeshInstanceBatches.Contains(BatchKey))
            {
                ViewportMeshInstanceBatches.Add(BatchKey,SVulkanMeshInstanceBatch());
                ViewportMeshInstanceBatches[BatchKey].Mesh=Mesh;
                ViewportMeshInstanceBatches[BatchKey].Material=Material;
            }
            ViewportMeshInstanceBatches[BatchKey].ModelMatrices.Add(MeshInstance.GetModelMatrix());
        }
    }
    //将批次模型位置数据写入
    for(auto& Batch: ViewportMeshInstanceBatches)
    {
        Batch.Value.UpdateUniformBuffer();
    }



    //统计描述符数量
    SVulkanDescriptorPoolSize PoolSize;
    
    //单个instance的描述符
    PoolSize.SetNum=MeshInstances.Num();
    PoolSize+=CVulkanContext::Get()->GetSceneGlobal()->ModelDescriptorSetLayout.DescriptorNums * MeshInstances.Num();
    CVulkanContext::Get()->GetAutoResetDescriptorPool()->MeshInstancePool.PoolSize+=PoolSize;

    //批次的描述符
    for(auto& Batch: ViewportMeshInstanceBatches)
    {
        Batch.Value.CountDescriptorSet();
    }

    for(auto& DirectionalLightBatch: DirectionalLightShadowMapMeshMap)
    {
        for(auto& MeshBatch: DirectionalLightBatch)
        {
            MeshBatch.Value.CountDescriptorSet();
        }
    }

    for(auto& MeshInstance: MeshInstances)
    {
        for(auto& Material: MeshInstance.Materials)
        {
            Material->PrepareSelfRecord();
        }
    }
    
}

void CVulkanMeshInstances::CreateDescriptorSet()
{
    for(auto& MeshInstance: MeshInstances)
    {
        MeshInstance.CreateDescriptorSet();
    }

    //创建批次的描述符
    for(auto& Batch: ViewportMeshInstanceBatches)
    {
        Batch.Value.CreateDescriptorSet();
    }
}

void CVulkanMeshInstances::RecordGBuffersDrawCommands(vk::CommandBuffer InCmdBuffer, std::shared_ptr<CSceneParameterBuffer> SceneParameterBuffer)
{
    // for(auto& MeshInstanceIndex: ViewportMeshMap)
    // {
    //     MeshInstances[MeshInstanceIndex].RecordGBuffersDrawCommands(InCmdBuffer,SceneParameterBuffer);
    // }

    for(auto& MeshBatch:ViewportMeshInstanceBatches)
    {
        MeshBatch.Value.RecordGBuffersDrawCommands(InCmdBuffer,SceneParameterBuffer);
    }

}

void CVulkanMeshInstances::RecordUnlitDrawCommands(vk::CommandBuffer InCmdBuffer, std::shared_ptr<CSceneParameterBuffer> SceneParameterBuffer)
{
    // for(auto& MeshInstance: MeshInstances)
    // {
    //     MeshInstance.RecordUnlitDrawCommands(InCmdBuffer,SceneParameterBuffer);
    // }

    for(auto& MeshBatch:ViewportMeshInstanceBatches)
    {
        MeshBatch.Value.RecordUnlitDrawCommands(InCmdBuffer,SceneParameterBuffer);
    }
}


CVulkanMeshInstance::CVulkanMeshInstance()
{
    ModelUniformBuffer=std::make_shared<TVulkanUniformBuffer<CVulkanContext::SDefferShadingVertexModelUniform>>();
}

void CVulkanMeshInstance::SetData(const SPreRenderMeshInstance &InMeshInstance)
{
    Position=InMeshInstance.Position;
    Rotation=InMeshInstance.Rotation;
    Scale=InMeshInstance.Scale;
    BoundingSphereRadius=InMeshInstance.BoundingSphereRadius;
    CastShadow=InMeshInstance.CastShadow;
    MeshSections.Resize(InMeshInstance.MeshSections.Num());
    for(int32_t SectionIndex=0;SectionIndex<InMeshInstance.MeshSections.Num();++SectionIndex)
    {
        auto PreRenderMesh=InMeshInstance.MeshSections[SectionIndex];
        auto Mesh=CVulkanContext::Get()->ToVulkanMesh(PreRenderMesh->WriteInData);
        MeshSections[SectionIndex]=Mesh;
    }
    Materials.Resize(InMeshInstance.Materials.Num());
    for(int32_t MaterialIndex=0;MaterialIndex<InMeshInstance.Materials.Num();++MaterialIndex)
    {
        auto PreRenderMaterial=InMeshInstance.Materials[MaterialIndex];
        auto Material=CVulkanContext::Get()->ToVulkanMaterial(PreRenderMaterial);
        Materials[MaterialIndex]=Material;
    }

    //设置模型矩阵
    CVulkanContext::SDefferShadingVertexModelUniform ModelUniform;
    ModelUniform.ModelMatrix = GetModelMatrix();
    ModelUniformBuffer->WriteData(ModelUniform);


}

// void CVulkanMeshInstance::RecordUnlitDrawCommands(vk::CommandBuffer InCmdBuffer, std::shared_ptr<CSceneParameterBuffer> SceneParameterBuffer)
// {
//     for(int32_t MeshIndex=0;MeshIndex<Data.MeshSections.Num();++MeshIndex)
//     {
//         auto Mesh = Data.MeshSections[MeshIndex];
//         auto Material = Data.Materials[MeshIndex];
//         if(!Material->CanUnlitRender())
//         {
//             continue;
//         }

//         //bind pipeline
//         InCmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, Material->Pipeline);

//         //bind descriptor sets
//         InCmdBuffer.bindDescriptorSets(
//             vk::PipelineBindPoint::eGraphics
//             , Material->PipelineLayout
//             , 0
//             , {
//                 Material->DescriptorSet, //用户自定义的材质参数
//                 ModelBufferDescriptorSet, //模型参数
//                 SceneParameterBuffer->GetDescriptorSet() //场景参数
//             }
//             , nullptr);

//         //draw vertex buffer
//         Mesh->RecordDrawCommands(InCmdBuffer);
//     }
// }

// void CVulkanMeshInstance::RecordGBuffersDrawCommands(vk::CommandBuffer InCmdBuffer, std::shared_ptr<CSceneParameterBuffer> SceneParameterBuffer)
// {

//     for(int32_t MeshIndex=0;MeshIndex<Data.MeshSections.Num();++MeshIndex)
//     {
//         auto Mesh = Data.MeshSections[MeshIndex];
//         auto Material = Data.Materials[MeshIndex];

//         if(!Material->CanDefferRender())
//         {
//             continue;
//         }

//         //bind pipeline
//         InCmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, Material->Pipeline);

//         //bind descriptor sets
//         InCmdBuffer.bindDescriptorSets(
//             vk::PipelineBindPoint::eGraphics
//             , Material->PipelineLayout
//             , 0
//             , {
//                 Material->DescriptorSet, //用户自定义的材质参数
//                 ModelBufferDescriptorSet, //模型参数
//                 SceneParameterBuffer->GetDescriptorSet() //场景参数
//             }
//             , nullptr);

//         //draw vertex buffer
//         Mesh->RecordDrawCommands(InCmdBuffer);
//     }
// }

void CVulkanMeshInstance::RecordDrawVertexCommands(vk::CommandBuffer InCmdBuffer)
{
    for(int32_t MeshIndex=0;MeshIndex<MeshSections.Num();++MeshIndex)
    {
        auto Mesh = MeshSections[MeshIndex];
        Mesh->RecordDrawCommands(InCmdBuffer);
    }
}

SMatrix4x4 CVulkanMeshInstance::GetModelMatrix() const
{
    return SMatrix4x4(Position, Rotation, Scale);
}

void CVulkanMeshInstance::CreateDescriptorSet()
{

    //创建描述符集
    TVector<vk::DescriptorSetLayout> DescriptorSetLayouts = {
        CVulkanContext::Get()->GetSceneGlobal()->ModelDescriptorSetLayout.Layout
    };

    //create descriptor set
    vk::DescriptorSetAllocateInfo DescriptorSetAllocateInfo = vk::DescriptorSetAllocateInfo()
        .setDescriptorPool(CVulkanContext::Get()->GetAutoResetDescriptorPool()->MeshInstancePool.Pool)
        .setSetLayouts(DescriptorSetLayouts);

    ModelBufferDescriptorSet = CVulkanContext::Get()->GetDevice().allocateDescriptorSets(DescriptorSetAllocateInfo)[0];

    vk::DescriptorBufferInfo DescriptorBufferInfo = vk::DescriptorBufferInfo()
        .setBuffer(ModelUniformBuffer->GetBuffer())
        .setOffset(0)
        .setRange(ModelUniformBuffer->GetSize());

    vk::WriteDescriptorSet WriteDescriptorSet = vk::WriteDescriptorSet()
        .setDstSet(ModelBufferDescriptorSet)
        .setDstBinding(0)
        .setDstArrayElement(0)
        .setDescriptorType(vk::DescriptorType::eUniformBuffer)
        .setDescriptorCount(1)
        .setPBufferInfo(&DescriptorBufferInfo);

    CVulkanContext::Get()->GetDevice().updateDescriptorSets(WriteDescriptorSet, nullptr);

    for(auto& Material: Materials)
    {
        Material->MakeSureDescriptorSetAvaliable();
    }
}

SVulkanMeshInstanceBatch::SVulkanMeshInstanceBatch()
{
    ModelUniformBuffer=std::make_shared<CVulkanUniformBuffer>();
}

void SVulkanMeshInstanceBatch::RecordGBuffersDrawCommands(vk::CommandBuffer InCmdBuffer, std::shared_ptr<CSceneParameterBuffer> SceneParameterBuffer)
{
    if(!Material->CanDefferRender())
    {
        return;
    }

    int32_t BatchNum=ModelMatrices.Num()/MESH_BATCH_SIZE;
    if(ModelMatrices.Num()%MESH_BATCH_SIZE!=0)
    {
        ++BatchNum;
    }

    for(int32_t BatchIndex=0; BatchIndex<BatchNum;++BatchIndex)
    {
        

        //bind pipeline
        InCmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, Material->Pipeline->Pipeline);

        //bind descriptor sets
        InCmdBuffer.bindDescriptorSets(
            vk::PipelineBindPoint::eGraphics
            , Material->Pipeline->PipelineLayout
            , 0
            , {
                Material->DescriptorSet, //用户自定义的材质参数
                ModelBufferDescriptorSets[BatchIndex], //模型参数
                SceneParameterBuffer->GetDescriptorSet() //场景参数
            }
            , nullptr);

        //这个小批次的大小
        int32_t BatchSize=
            CMath::Min(MESH_BATCH_SIZE,ModelMatrices.Num()-BatchIndex*MESH_BATCH_SIZE);

        //draw vertex buffer
        Mesh->RecordDrawCommands(InCmdBuffer,BatchSize,0);
    }
}

void SVulkanMeshInstanceBatch::RecordUnlitDrawCommands(vk::CommandBuffer InCmdBuffer, std::shared_ptr<CSceneParameterBuffer> SceneParameterBuffer)
{
    if(!Material->CanUnlitRender())
    {
        return;
    }

    int32_t BatchNum=ModelMatrices.Num()/MESH_BATCH_SIZE;
    if(ModelMatrices.Num()%MESH_BATCH_SIZE!=0)
    {
        ++BatchNum;
    }

    for(int32_t BatchIndex=0; BatchIndex<BatchNum;++BatchIndex)
    {
    
        //bind pipeline
        InCmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, Material->Pipeline->Pipeline);

        //bind descriptor sets
        InCmdBuffer.bindDescriptorSets(
            vk::PipelineBindPoint::eGraphics
            , Material->Pipeline->PipelineLayout
            , 0
            , {
                Material->DescriptorSet, //用户自定义的材质参数
                ModelBufferDescriptorSets[BatchIndex], //模型参数
                SceneParameterBuffer->GetDescriptorSet() //场景参数
            }
            , nullptr);

        //这个小批次的大小
        int32_t BatchSize=
            CMath::Min(MESH_BATCH_SIZE,ModelMatrices.Num()-BatchIndex*MESH_BATCH_SIZE);

        //draw vertex buffer
        Mesh->RecordDrawCommands(InCmdBuffer,BatchSize,0);
    }
}

void SVulkanMeshInstanceBatch::CountDescriptorSet()
{
    SVulkanDescriptorPoolSize PoolSize;
    int32_t SetNum=ModelMatrices.Num() / MESH_BATCH_SIZE;
    if(ModelMatrices.Num()%MESH_BATCH_SIZE!=0)
    {
        ++SetNum;
    }


    PoolSize.SetNum=SetNum;
    PoolSize+=CVulkanContext::Get()->GetSceneGlobal()->BatchModelDescriptorSetLayout.DescriptorNums * SetNum;
    CVulkanContext::Get()->GetAutoResetDescriptorPool()->MeshInstancePool.PoolSize+=PoolSize;
}

void SVulkanMeshInstanceBatch::UpdateUniformBuffer()
{
    TVector<CVulkanContext::SDefferShadingVertexModelUniform> ModelUniforms;
    ModelUniforms.Reserve(ModelMatrices.Num());
    for(auto& ModelMatrix: ModelMatrices)
    {
        CVulkanContext::SDefferShadingVertexModelUniform ModelUniform;
        ModelUniform.ModelMatrix = ModelMatrix;
        ModelUniforms.Add(ModelUniform);
    }

    ModelUniformBuffer->Resize(ModelUniforms.Num() * sizeof(CVulkanContext::SDefferShadingVertexModelUniform));
    ModelUniformBuffer->WriteData(ModelUniforms.Data(),ModelUniforms.Num() * sizeof(CVulkanContext::SDefferShadingVertexModelUniform));
}

void SVulkanMeshInstanceBatch::CreateDescriptorSet()
{
    //创建描述符集
    TVector<vk::DescriptorSetLayout> DescriptorSetLayouts=
    {
        CVulkanContext::Get()->GetSceneGlobal()->BatchModelDescriptorSetLayout.Layout
    };
    
    //create descriptor set
    vk::DescriptorSetAllocateInfo DescriptorSetAllocateInfo = vk::DescriptorSetAllocateInfo()
        .setDescriptorPool(CVulkanContext::Get()->GetAutoResetDescriptorPool()->MeshInstancePool.Pool)
        .setSetLayouts(DescriptorSetLayouts);

    int32_t BatchNum=ModelMatrices.Num()/MESH_BATCH_SIZE;
    if(ModelMatrices.Num()%MESH_BATCH_SIZE!=0)
    {
        ++BatchNum;
    }

    for(int32_t BatchIndex=0; BatchIndex<BatchNum;++BatchIndex)
    {
        //这个小批次的大小
        int32_t BatchSize=
            CMath::Min(MESH_BATCH_SIZE,ModelMatrices.Num()-BatchIndex*MESH_BATCH_SIZE);

        //这个小批次的描述符
        auto ModelBufferDescriptorSet = CVulkanContext::Get()->GetDevice().allocateDescriptorSets(DescriptorSetAllocateInfo)[0];
        ModelBufferDescriptorSets.Add(ModelBufferDescriptorSet);

        vk::DescriptorBufferInfo DescriptorBufferInfo = vk::DescriptorBufferInfo()
            .setBuffer(ModelUniformBuffer->GetBuffer())
            .setOffset(BatchIndex*MESH_BATCH_SIZE*sizeof(CVulkanContext::SDefferShadingVertexModelUniform) )
            .setRange(BatchSize*sizeof(CVulkanContext::SDefferShadingVertexModelUniform));

        vk::WriteDescriptorSet WriteDescriptorSet = vk::WriteDescriptorSet()
            .setDstSet(ModelBufferDescriptorSet)
            .setDstBinding(0)
            .setDstArrayElement(0)
            .setDescriptorType(vk::DescriptorType::eUniformBuffer)
            .setDescriptorCount(1)
            .setPBufferInfo(&DescriptorBufferInfo);

        CVulkanContext::Get()->GetDevice().updateDescriptorSets(WriteDescriptorSet, nullptr);
    }
}

SVulkanShadowmapMeshBatch::SVulkanShadowmapMeshBatch(std::shared_ptr<CVulkanMesh> InMesh)
{
    Mesh=InMesh;
    ModelUniformBuffer=std::make_shared<CVulkanUniformBuffer>();
}

void SVulkanShadowmapMeshBatch::CountDescriptorSet()
{
    SVulkanDescriptorPoolSize PoolSize;
    int32_t SetNum=ModelMatrices.Num() / MESH_BATCH_SIZE;
    if(ModelMatrices.Num()%MESH_BATCH_SIZE!=0)
    {
        ++SetNum;
    }
    PoolSize.SetNum=SetNum;
    PoolSize+=CVulkanContext::Get()->GetSceneGlobal()->BatchModelDescriptorSetLayout.DescriptorNums * SetNum;
    CVulkanContext::Get()->GetAutoResetDescriptorPool()->MeshInstancePool.PoolSize+=PoolSize;
}

void SVulkanShadowmapMeshBatch::UpdateUniformBuffer()
{
    ModelUniformBuffer->Resize(ModelMatrices.Num() * sizeof(CVulkanContext::SDefferShadingVertexModelUniform));

    TVector<CVulkanContext::SDefferShadingVertexModelUniform> ModelUniforms;
    ModelUniforms.Reserve(ModelMatrices.Num());

    for(auto& ModelMatrix: ModelMatrices)
    {
        CVulkanContext::SDefferShadingVertexModelUniform ModelUniform;
        ModelUniform.ModelMatrix = ModelMatrix;
        ModelUniforms.Add(ModelUniform);
    }
}

void SVulkanShadowmapMeshBatch::CreateDescriptorSet()
{
    //创建描述符集
    TVector<vk::DescriptorSetLayout> DescriptorSetLayouts=
    {
        CVulkanContext::Get()->GetSceneGlobal()->BatchModelDescriptorSetLayout.Layout
    };
    
    //create descriptor set
    vk::DescriptorSetAllocateInfo DescriptorSetAllocateInfo = vk::DescriptorSetAllocateInfo()
        .setDescriptorPool(CVulkanContext::Get()->GetAutoResetDescriptorPool()->MeshInstancePool.Pool)
        .setSetLayouts(DescriptorSetLayouts);

    int32_t BatchNum=ModelMatrices.Num()/MESH_BATCH_SIZE;
    if(ModelMatrices.Num()%MESH_BATCH_SIZE!=0)
    {
        ++BatchNum;
    }

    for(int32_t BatchIndex=0; BatchIndex<BatchNum;++BatchIndex)
    {
        //这个小批次的大小
        int32_t BatchSize=
            CMath::Min(MESH_BATCH_SIZE,ModelMatrices.Num()-BatchIndex*MESH_BATCH_SIZE);

        //这个小批次的描述符
        auto ModelBufferDescriptorSet = CVulkanContext::Get()->GetDevice().allocateDescriptorSets(DescriptorSetAllocateInfo)[0];
        ModelBufferDescriptorSets.Add(ModelBufferDescriptorSet);

        vk::DescriptorBufferInfo DescriptorBufferInfo = vk::DescriptorBufferInfo()
            .setBuffer(ModelUniformBuffer->GetBuffer())
            .setOffset(BatchIndex*MESH_BATCH_SIZE*sizeof(CVulkanContext::SDefferShadingVertexModelUniform) )
            .setRange(BatchSize*sizeof(CVulkanContext::SDefferShadingVertexModelUniform));

        vk::WriteDescriptorSet WriteDescriptorSet = vk::WriteDescriptorSet()
            .setDstSet(ModelBufferDescriptorSet)
            .setDstBinding(0)
            .setDstArrayElement(0)
            .setDescriptorType(vk::DescriptorType::eUniformBuffer)
            .setDescriptorCount(1)
            .setPBufferInfo(&DescriptorBufferInfo);

        CVulkanContext::Get()->GetDevice().updateDescriptorSets(WriteDescriptorSet, nullptr);
    }
}
